Add more font private data.
authorTor Lillqvist <tml@iki.fi>
Wed, 20 Oct 1999 22:58:37 +0000 (22:58 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Wed, 20 Oct 1999 22:58:37 +0000 (22:58 +0000)
1999-10-21  Tor Lillqvist  <tml@iki.fi>

* gdk/win32/gdkprivate.h: Add more font private data.

* gdk/win32/gdkfont.c
* gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
fonts and strings. Now works much better. You still have to
have a correct font selected, though. No fontset emulation yet.

13 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gdk/win32/gdkdraw.c
gdk/win32/gdkdrawable-win32.c
gdk/win32/gdkfont-win32.c
gdk/win32/gdkfont.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkprivate.h

index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index a13a2c7c7072d769b905d56659405a481268416b..c21b32e9325f7730627137e62b61f16f343327c1 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-21  Tor Lillqvist  <tml@iki.fi>
+
+       * gdk/win32/gdkprivate.h: Add more font private data.
+
+       * gdk/win32/gdkfont.c
+       * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset
+       fonts and strings. Now works much better. You still have to
+       have a correct font selected, though. No fontset emulation yet.
+
 1999-10-19  Tor Lillqvist  <tml@iki.fi>
 
        * gtk/maketypes.awk: Use G_OS_WIN32.
index 8006e1e864f79986262ce28a6cc116d0ff414586..593c98cd80a9f21bfb73c72399829191834a1a2b 100644 (file)
@@ -455,6 +455,8 @@ gdk_draw_text (GdkDrawable *drawable,
   HDC hdc;
   HFONT xfont;
   HGDIOBJ oldfont;
+  wchar_t *wcstr;
+  gint wlen;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -463,6 +465,10 @@ gdk_draw_text (GdkDrawable *drawable,
 
   if (GDK_DRAWABLE_DESTROYED (drawable))
     return;
+
+  if (text_length == 0)
+    return;
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
@@ -482,9 +488,24 @@ gdk_draw_text (GdkDrawable *drawable,
       
       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
        g_warning ("gdk_draw_text: SelectObject failed");
-      if (!TextOutA (hdc, x, y, text, text_length))
-       g_warning ("gdk_draw_text: TextOutA failed");
-      SelectObject (hdc, oldfont);
+      if (font_private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
+         else if (!TextOutW (hdc, x, y, wcstr, wlen))
+           g_warning ("gdk_draw_text: TextOutW failed");
+         g_free (wcstr);
+       }
+      else
+       {
+         if (!TextOutA (hdc, x, y, text, text_length))
+           g_warning ("gdk_draw_text: TextOutA failed");
+       }
+      if (oldfont != NULL)
+       SelectObject (hdc, oldfont);
       gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
@@ -503,7 +524,7 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
   GdkDrawablePrivate *drawable_private;
   GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
-  gint i;
+  gint i, wlen;
   wchar_t *wcstr;
   guchar *str;
 
@@ -514,6 +535,10 @@ gdk_draw_text_wc (GdkDrawable       *drawable,
 
   if (GDK_DRAWABLE_DESTROYED (drawable))
     return;
+
+  if (text_length == 0)
+    return;
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
@@ -535,8 +560,8 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
                               text_length));
       
       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-       g_warning ("gdk_draw_text: SelectObject failed");
-#if 0 /* No. Don't use TextOutW. Compare to the X11 version,
+         g_warning ("gdk_draw_text_wc: SelectObject failed");
+#if 0 /* No. Don't use TextOutW directly. Compare to the X11 version,
        * it uses plain XDrawString for GDK_FONT_FONT fonts, too.
        * TextOutW by definition interprets the string as Unicode.
        * We don't have that, but either chars from some single-byte codepage
@@ -546,17 +571,32 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
       if (!TextOutW (hdc, x, y, wcstr, text_length))
-       g_warning ("gdk_draw_text: TextOutW failed");
+       g_warning ("gdk_draw_text_wc: TextOutW failed");
       g_free (wcstr);
 #else
       str = g_new (guchar, text_length);
-      for (i=0; i<text_length; i++)
+      for (i = 0; i < text_length; i++)
        str[i] = text[i];
-      if (!TextOutA (hdc, x, y, str, text_length))
-       g_warning ("gdk_draw_text: TextOutA failed");
+      if (font_private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
+                                          str, text_length,
+                                          wcstr, text_length)) == 0)
+           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
+         else if (!TextOutW (hdc, x, y, wcstr, wlen))
+           g_warning ("gdk_draw_text_wc: TextOutW failed");
+         g_free (wcstr);
+       }
+      else
+       {
+         if (!TextOutA (hdc, x, y, str, text_length))
+           g_warning ("gdk_draw_text_wc: TextOutA failed");
+       }
       g_free (str);
 #endif
-      SelectObject (hdc, oldfont);
+      if (oldfont != NULL)
+       SelectObject (hdc, oldfont);
       gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
index 8006e1e864f79986262ce28a6cc116d0ff414586..593c98cd80a9f21bfb73c72399829191834a1a2b 100644 (file)
@@ -455,6 +455,8 @@ gdk_draw_text (GdkDrawable *drawable,
   HDC hdc;
   HFONT xfont;
   HGDIOBJ oldfont;
+  wchar_t *wcstr;
+  gint wlen;
 
   g_return_if_fail (drawable != NULL);
   g_return_if_fail (font != NULL);
@@ -463,6 +465,10 @@ gdk_draw_text (GdkDrawable *drawable,
 
   if (GDK_DRAWABLE_DESTROYED (drawable))
     return;
+
+  if (text_length == 0)
+    return;
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
@@ -482,9 +488,24 @@ gdk_draw_text (GdkDrawable *drawable,
       
       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
        g_warning ("gdk_draw_text: SelectObject failed");
-      if (!TextOutA (hdc, x, y, text, text_length))
-       g_warning ("gdk_draw_text: TextOutA failed");
-      SelectObject (hdc, oldfont);
+      if (font_private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
+         else if (!TextOutW (hdc, x, y, wcstr, wlen))
+           g_warning ("gdk_draw_text: TextOutW failed");
+         g_free (wcstr);
+       }
+      else
+       {
+         if (!TextOutA (hdc, x, y, text, text_length))
+           g_warning ("gdk_draw_text: TextOutA failed");
+       }
+      if (oldfont != NULL)
+       SelectObject (hdc, oldfont);
       gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
@@ -503,7 +524,7 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
   GdkDrawablePrivate *drawable_private;
   GdkFontPrivate *font_private;
   GdkGCPrivate *gc_private;
-  gint i;
+  gint i, wlen;
   wchar_t *wcstr;
   guchar *str;
 
@@ -514,6 +535,10 @@ gdk_draw_text_wc (GdkDrawable       *drawable,
 
   if (GDK_DRAWABLE_DESTROYED (drawable))
     return;
+
+  if (text_length == 0)
+    return;
+
   drawable_private = (GdkDrawablePrivate*) drawable;
   gc_private = (GdkGCPrivate*) gc;
   font_private = (GdkFontPrivate*) font;
@@ -535,8 +560,8 @@ gdk_draw_text_wc (GdkDrawable        *drawable,
                               text_length));
       
       if ((oldfont = SelectObject (hdc, xfont)) == NULL)
-       g_warning ("gdk_draw_text: SelectObject failed");
-#if 0 /* No. Don't use TextOutW. Compare to the X11 version,
+         g_warning ("gdk_draw_text_wc: SelectObject failed");
+#if 0 /* No. Don't use TextOutW directly. Compare to the X11 version,
        * it uses plain XDrawString for GDK_FONT_FONT fonts, too.
        * TextOutW by definition interprets the string as Unicode.
        * We don't have that, but either chars from some single-byte codepage
@@ -546,17 +571,32 @@ gdk_draw_text_wc (GdkDrawable      *drawable,
       for (i = 0; i < text_length; i++)
        wcstr[i] = text[i];
       if (!TextOutW (hdc, x, y, wcstr, text_length))
-       g_warning ("gdk_draw_text: TextOutW failed");
+       g_warning ("gdk_draw_text_wc: TextOutW failed");
       g_free (wcstr);
 #else
       str = g_new (guchar, text_length);
-      for (i=0; i<text_length; i++)
+      for (i = 0; i < text_length; i++)
        str[i] = text[i];
-      if (!TextOutA (hdc, x, y, str, text_length))
-       g_warning ("gdk_draw_text: TextOutA failed");
+      if (font_private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (font_private->codepage, 0,
+                                          str, text_length,
+                                          wcstr, text_length)) == 0)
+           g_warning ("gdk_draw_text: MultiByteToWideChar failed");
+         else if (!TextOutW (hdc, x, y, wcstr, wlen))
+           g_warning ("gdk_draw_text_wc: TextOutW failed");
+         g_free (wcstr);
+       }
+      else
+       {
+         if (!TextOutA (hdc, x, y, str, text_length))
+           g_warning ("gdk_draw_text_wc: TextOutA failed");
+       }
       g_free (str);
 #endif
-      SelectObject (hdc, oldfont);
+      if (oldfont != NULL)
+       SelectObject (hdc, oldfont);
       gdk_gc_postdraw (drawable_private, gc_private);
     }
   else
index 9c2649eded73c3232077191301002501bd33fc20..d28c1f77c0615491ab1ad52cb0eb032e83fc7d97 100644 (file)
@@ -89,6 +89,33 @@ gdk_font_hash_lookup (GdkFontType type, const gchar *font_name)
     }
 }
 
+static const char *
+charset_name (DWORD charset)
+{
+  switch (charset)
+    {
+    case ANSI_CHARSET: return "ANSI";
+    case DEFAULT_CHARSET: return "DEFAULT";
+    case SYMBOL_CHARSET: return "SYMBOL";
+    case SHIFTJIS_CHARSET: return "SHIFTJIS";
+    case HANGEUL_CHARSET: return "HANGEUL";
+    case GB2312_CHARSET: return "GB2312";
+    case CHINESEBIG5_CHARSET: return "CHINESEBIG5";
+    case JOHAB_CHARSET: return "JOHAB";
+    case HEBREW_CHARSET: return "HEBREW";
+    case ARABIC_CHARSET: return "ARABIC";
+    case GREEK_CHARSET: return "GREEK";
+    case TURKISH_CHARSET: return "TURKISH";
+    case VIETNAMESE_CHARSET: return "VIETNAMESE";
+    case THAI_CHARSET: return "THAI";
+    case EASTEUROPE_CHARSET: return "EASTEUROPE";
+    case RUSSIAN_CHARSET: return "RUSSIAN";
+    case MAC_CHARSET: return "MAC";
+    case BALTIC_CHARSET: return "BALTIC";
+    }
+  return "unknown";
+}
+
 GdkFont*
 gdk_font_load (const gchar *font_name)
 {
@@ -98,6 +125,7 @@ gdk_font_load (const gchar *font_name)
   LOGFONT logfont;
   HGDIOBJ oldfont;
   TEXTMETRIC textmetric;
+  CHARSETINFO csi;
   HANDLE *f;
   DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
     fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
@@ -283,10 +311,8 @@ gdk_font_load (const gchar *font_name)
          fdwCharSet = HANGEUL_CHARSET;
        else if (g_strcasecmp (encoding, "chinesebig5") == 0)
          fdwCharSet = CHINESEBIG5_CHARSET;
-#ifdef JOHAB_CHARSET
        else if (g_strcasecmp (encoding, "johab") == 0)
          fdwCharSet = JOHAB_CHARSET;
-#endif
        else if (g_strcasecmp (encoding, "hebrew") == 0)
          fdwCharSet = HEBREW_CHARSET;
        else if (g_strcasecmp (encoding, "arabic") == 0)
@@ -395,12 +421,21 @@ gdk_font_load (const gchar *font_name)
   GetObject (private->xfont, sizeof (logfont), &logfont);
   oldfont = SelectObject (gdk_DC, private->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
+  private->charset = GetTextCharsetInfo (gdk_DC, &private->fs, 0);
   SelectObject (gdk_DC, oldfont);
+  TranslateCharsetInfo ((DWORD *) private->charset, &csi, TCI_SRCCHARSET);
+  private->codepage = csi.ciACP;
+  GetCPInfo (private->codepage, &private->cpinfo);
   font->ascent = textmetric.tmAscent;
   font->descent = textmetric.tmDescent;
 
-  GDK_NOTE (MISC, g_print ("... = %#x asc %d desc %d\n",
-                          private->xfont, font->ascent, font->descent));
+  GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d (max %d bytes) "
+                          "asc %d desc %d\n",
+                          private->xfont,
+                          charset_name (private->charset),
+                          private->codepage,
+                          private->cpinfo.MaxCharSize,
+                          font->ascent, font->descent));
 
   /* This memory is leaked, so shoot me. */
   f = g_new (HANDLE, 1);
@@ -429,6 +464,9 @@ gdk_font_ref (GdkFont *font)
 
   private = (GdkFontPrivate*) font;
   private->ref_count += 1;
+
+  GDK_NOTE (MISC, g_print ("gdk_font_ref %#x %d\n",
+                          private->xfont, private->ref_count));
   return font;
 }
 
@@ -442,6 +480,12 @@ gdk_font_unref (GdkFont *font)
   g_return_if_fail (private->ref_count > 0);
 
   private->ref_count -= 1;
+
+  GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n",
+                          private->xfont,
+                          private->ref_count,
+                          (private->ref_count == 0 ? " freeing" : "")));
+
   if (private->ref_count == 0)
     {
       gdk_font_hash_remove (font->type, font);
@@ -449,8 +493,6 @@ gdk_font_unref (GdkFont *font)
       switch (font->type)
        {
        case GDK_FONT_FONT:
-         GDK_NOTE (MISC, g_print ("gdk_font_unref %#x\n", private->xfont));
-
          gdk_xid_table_remove ((HANDLE) ((guint) private->xfont + HFONT_DITHER));
          DeleteObject (private->xfont);
          break;
@@ -513,18 +555,39 @@ gdk_text_width (GdkFont      *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
-  gint width;
+  gint width, wlen;
+  wchar_t *wcstr;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_width: MultiByteToWideChar failed");
+             size.cx = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       width = size.cx;
       break;
@@ -545,11 +608,14 @@ gdk_text_width_wc (GdkFont          *font,
   SIZE size;
   wchar_t *wcstr;
   guchar *str;
-  gint i, width;
+  gint i, width, wlen;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
@@ -566,9 +632,26 @@ gdk_text_width_wc (GdkFont   *font,
       g_free (wcstr);
 #else
       str = g_new (guchar, text_length);
-      for (i=0; i<text_length; i++)
+      for (i = 0; i < text_length; i++)
        str[i] = text[i];
-      GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          str, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_width_wc: MultiByteToWideChar failed");
+             size.cx = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
+       }
       g_free (str);
 #endif
       SelectObject (gdk_DC, oldfont);
@@ -618,17 +701,52 @@ gdk_text_extents (GdkFont     *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
+  gint wlen;
+  wchar_t *wcstr;
 
   g_return_if_fail (font != NULL);
   g_return_if_fail (text != NULL);
 
+  if (text_length == 0)
+    {
+      if (lbearing)
+       *lbearing = 0;
+      if (rbearing)
+       *rbearing = 0;
+      if (width)
+       *width = 0;
+      if (ascent)
+       *ascent = 0;
+      if (descent)
+       *descent = 0;
+      return;
+    }
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_extents: MultiByteToWideChar failed");
+             size.cx = 0;
+             size.cy = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       /* XXX This is all quite bogus */
       if (lbearing)
@@ -667,6 +785,21 @@ gdk_text_extents_wc (GdkFont        *font,
   g_return_if_fail (font != NULL);
   g_return_if_fail (text != NULL);
 
+  if (text_length == 0)
+    {
+      if (lbearing)
+       *lbearing = 0;
+      if (rbearing)
+       *rbearing = 0;
+      if (width)
+       *width = 0;
+      if (ascent)
+       *ascent = 0;
+      if (descent)
+       *descent = 0;
+      return;
+    }
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
@@ -765,18 +898,41 @@ gdk_text_height (GdkFont     *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
-  gint height;
+  gint height, wlen;
+  wchar_t *wcstr;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32 (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_height: MultiByteToWideChar failed "
+                        "text = %.*s (%d)",
+                        text_length, text, text_length);
+             size.cy = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       height = size.cy;
       break;
index 9c2649eded73c3232077191301002501bd33fc20..d28c1f77c0615491ab1ad52cb0eb032e83fc7d97 100644 (file)
@@ -89,6 +89,33 @@ gdk_font_hash_lookup (GdkFontType type, const gchar *font_name)
     }
 }
 
+static const char *
+charset_name (DWORD charset)
+{
+  switch (charset)
+    {
+    case ANSI_CHARSET: return "ANSI";
+    case DEFAULT_CHARSET: return "DEFAULT";
+    case SYMBOL_CHARSET: return "SYMBOL";
+    case SHIFTJIS_CHARSET: return "SHIFTJIS";
+    case HANGEUL_CHARSET: return "HANGEUL";
+    case GB2312_CHARSET: return "GB2312";
+    case CHINESEBIG5_CHARSET: return "CHINESEBIG5";
+    case JOHAB_CHARSET: return "JOHAB";
+    case HEBREW_CHARSET: return "HEBREW";
+    case ARABIC_CHARSET: return "ARABIC";
+    case GREEK_CHARSET: return "GREEK";
+    case TURKISH_CHARSET: return "TURKISH";
+    case VIETNAMESE_CHARSET: return "VIETNAMESE";
+    case THAI_CHARSET: return "THAI";
+    case EASTEUROPE_CHARSET: return "EASTEUROPE";
+    case RUSSIAN_CHARSET: return "RUSSIAN";
+    case MAC_CHARSET: return "MAC";
+    case BALTIC_CHARSET: return "BALTIC";
+    }
+  return "unknown";
+}
+
 GdkFont*
 gdk_font_load (const gchar *font_name)
 {
@@ -98,6 +125,7 @@ gdk_font_load (const gchar *font_name)
   LOGFONT logfont;
   HGDIOBJ oldfont;
   TEXTMETRIC textmetric;
+  CHARSETINFO csi;
   HANDLE *f;
   DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet,
     fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily;
@@ -283,10 +311,8 @@ gdk_font_load (const gchar *font_name)
          fdwCharSet = HANGEUL_CHARSET;
        else if (g_strcasecmp (encoding, "chinesebig5") == 0)
          fdwCharSet = CHINESEBIG5_CHARSET;
-#ifdef JOHAB_CHARSET
        else if (g_strcasecmp (encoding, "johab") == 0)
          fdwCharSet = JOHAB_CHARSET;
-#endif
        else if (g_strcasecmp (encoding, "hebrew") == 0)
          fdwCharSet = HEBREW_CHARSET;
        else if (g_strcasecmp (encoding, "arabic") == 0)
@@ -395,12 +421,21 @@ gdk_font_load (const gchar *font_name)
   GetObject (private->xfont, sizeof (logfont), &logfont);
   oldfont = SelectObject (gdk_DC, private->xfont);
   GetTextMetrics (gdk_DC, &textmetric);
+  private->charset = GetTextCharsetInfo (gdk_DC, &private->fs, 0);
   SelectObject (gdk_DC, oldfont);
+  TranslateCharsetInfo ((DWORD *) private->charset, &csi, TCI_SRCCHARSET);
+  private->codepage = csi.ciACP;
+  GetCPInfo (private->codepage, &private->cpinfo);
   font->ascent = textmetric.tmAscent;
   font->descent = textmetric.tmDescent;
 
-  GDK_NOTE (MISC, g_print ("... = %#x asc %d desc %d\n",
-                          private->xfont, font->ascent, font->descent));
+  GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d (max %d bytes) "
+                          "asc %d desc %d\n",
+                          private->xfont,
+                          charset_name (private->charset),
+                          private->codepage,
+                          private->cpinfo.MaxCharSize,
+                          font->ascent, font->descent));
 
   /* This memory is leaked, so shoot me. */
   f = g_new (HANDLE, 1);
@@ -429,6 +464,9 @@ gdk_font_ref (GdkFont *font)
 
   private = (GdkFontPrivate*) font;
   private->ref_count += 1;
+
+  GDK_NOTE (MISC, g_print ("gdk_font_ref %#x %d\n",
+                          private->xfont, private->ref_count));
   return font;
 }
 
@@ -442,6 +480,12 @@ gdk_font_unref (GdkFont *font)
   g_return_if_fail (private->ref_count > 0);
 
   private->ref_count -= 1;
+
+  GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n",
+                          private->xfont,
+                          private->ref_count,
+                          (private->ref_count == 0 ? " freeing" : "")));
+
   if (private->ref_count == 0)
     {
       gdk_font_hash_remove (font->type, font);
@@ -449,8 +493,6 @@ gdk_font_unref (GdkFont *font)
       switch (font->type)
        {
        case GDK_FONT_FONT:
-         GDK_NOTE (MISC, g_print ("gdk_font_unref %#x\n", private->xfont));
-
          gdk_xid_table_remove ((HANDLE) ((guint) private->xfont + HFONT_DITHER));
          DeleteObject (private->xfont);
          break;
@@ -513,18 +555,39 @@ gdk_text_width (GdkFont      *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
-  gint width;
+  gint width, wlen;
+  wchar_t *wcstr;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_width: MultiByteToWideChar failed");
+             size.cx = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       width = size.cx;
       break;
@@ -545,11 +608,14 @@ gdk_text_width_wc (GdkFont          *font,
   SIZE size;
   wchar_t *wcstr;
   guchar *str;
-  gint i, width;
+  gint i, width, wlen;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
@@ -566,9 +632,26 @@ gdk_text_width_wc (GdkFont   *font,
       g_free (wcstr);
 #else
       str = g_new (guchar, text_length);
-      for (i=0; i<text_length; i++)
+      for (i = 0; i < text_length; i++)
        str[i] = text[i];
-      GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          str, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_width_wc: MultiByteToWideChar failed");
+             size.cx = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
+       }
       g_free (str);
 #endif
       SelectObject (gdk_DC, oldfont);
@@ -618,17 +701,52 @@ gdk_text_extents (GdkFont     *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
+  gint wlen;
+  wchar_t *wcstr;
 
   g_return_if_fail (font != NULL);
   g_return_if_fail (text != NULL);
 
+  if (text_length == 0)
+    {
+      if (lbearing)
+       *lbearing = 0;
+      if (rbearing)
+       *rbearing = 0;
+      if (width)
+       *width = 0;
+      if (ascent)
+       *ascent = 0;
+      if (descent)
+       *descent = 0;
+      return;
+    }
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_extents: MultiByteToWideChar failed");
+             size.cx = 0;
+             size.cy = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       /* XXX This is all quite bogus */
       if (lbearing)
@@ -667,6 +785,21 @@ gdk_text_extents_wc (GdkFont        *font,
   g_return_if_fail (font != NULL);
   g_return_if_fail (text != NULL);
 
+  if (text_length == 0)
+    {
+      if (lbearing)
+       *lbearing = 0;
+      if (rbearing)
+       *rbearing = 0;
+      if (width)
+       *width = 0;
+      if (ascent)
+       *ascent = 0;
+      if (descent)
+       *descent = 0;
+      return;
+    }
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
@@ -765,18 +898,41 @@ gdk_text_height (GdkFont     *font,
   GdkFontPrivate *private;
   HGDIOBJ oldfont;
   SIZE size;
-  gint height;
+  gint height, wlen;
+  wchar_t *wcstr;
 
   g_return_val_if_fail (font != NULL, -1);
   g_return_val_if_fail (text != NULL, -1);
 
+  if (text_length == 0)
+    return 0;
+
   private = (GdkFontPrivate*) font;
 
   switch (font->type)
     {
     case GDK_FONT_FONT:
       oldfont = SelectObject (gdk_DC, private->xfont);
-      GetTextExtentPoint32 (gdk_DC, text, text_length, &size);
+      if (private->cpinfo.MaxCharSize > 1)
+       {
+         wcstr = g_new (wchar_t, text_length);
+         if ((wlen = MultiByteToWideChar (private->codepage, 0,
+                                          text, text_length,
+                                          wcstr, text_length)) == 0)
+           {
+             g_warning ("gdk_text_height: MultiByteToWideChar failed "
+                        "text = %.*s (%d)",
+                        text_length, text, text_length);
+             size.cy = 0;
+           }
+         else
+           GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
+         g_free (wcstr);
+       }
+      else
+       {
+         GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
+       }
       SelectObject (gdk_DC, oldfont);
       height = size.cy;
       break;
index 5df4fe73587254e0d8789006b723747a38c64ee3..a45044d8e635f0a5c5078f09a6fc600830319ff2 100644 (file)
 #define CLR_INVALID CLR_NONE
 #endif
 
+/* Some charsets are missing */
+#ifndef JOHAB_CHARSET
+#define JOHAB_CHARSET 130
+#endif
+#ifndef VIETNAMESE_CHARSET
+#define VIETNAMESE_CHARSET 163
+#endif
+
 /* MB_CUR_MAX is missing */
 #ifndef MB_CUR_MAX
 extern int *__imp___mb_cur_max;
@@ -300,6 +308,10 @@ struct _GdkFontPrivate
   guint ref_count;
 
   GSList *names;
+  DWORD charset;
+  UINT codepage;
+  CPINFO cpinfo;
+  FONTSIGNATURE fs;
 };
 
 struct _GdkCursorPrivate
index 5df4fe73587254e0d8789006b723747a38c64ee3..a45044d8e635f0a5c5078f09a6fc600830319ff2 100644 (file)
 #define CLR_INVALID CLR_NONE
 #endif
 
+/* Some charsets are missing */
+#ifndef JOHAB_CHARSET
+#define JOHAB_CHARSET 130
+#endif
+#ifndef VIETNAMESE_CHARSET
+#define VIETNAMESE_CHARSET 163
+#endif
+
 /* MB_CUR_MAX is missing */
 #ifndef MB_CUR_MAX
 extern int *__imp___mb_cur_max;
@@ -300,6 +308,10 @@ struct _GdkFontPrivate
   guint ref_count;
 
   GSList *names;
+  DWORD charset;
+  UINT codepage;
+  CPINFO cpinfo;
+  FONTSIGNATURE fs;
 };
 
 struct _GdkCursorPrivate